package com.winit.project.web;

import com.alibaba.fastjson.JSONObject;
import com.winit.common.base.beans.FileBaseInfo;
import com.winit.common.base.beans.LoginUser;
import com.winit.common.base.web.BaseController;
import com.winit.common.filter.UserInfoUtil;
import com.winit.common.util.JSONFileUtil;
import com.winit.common.util.ZipUtil;
import com.winit.project.manager.ProjectManager;
import com.winit.project.util.ProjectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by keel2008 on 16/9/27.
 */
@RestController(value = "newResourceController")
@RequestMapping("/project")
public class ResourceController extends BaseController {

    @Autowired
    private ProjectManager projectManager;

    private static final Logger logger = LoggerFactory.getLogger(ResourceController.class);

    /**
     * 获取工程相关文档列表
     * @param request
     * @return
     */
    @RequestMapping("/projectFileList")
    @ResponseBody
    public Map<String,Object> projectFileList(HttpServletRequest request){
        Map<String, Object> rtnMap = new HashMap<>();
        logger.info("获取工程相关文档开始");
        LoginUser userInfo = UserInfoUtil.getUserInfo(request);
        if (userInfo == null) {
            logger.info("获取工程相关文档,获取用户信息为空");
            return this.noUserRtn();
        }

        String projectName = request.getParameter("projectName");
        String type = request.getParameter("type");

        Assert.hasText(projectName, "获取工程相关文档,工程名为空");
        Assert.hasText(type, "获取工程相关文档,文件类型为空");

        JSONObject object = new JSONObject();

        try {
            List<FileBaseInfo> list = projectManager.projectFileList(projectName,type);
            rtnMap.put("code","0");
            object.put("list",list);
        } catch (Exception e) {
            logger.error("获取工程相关文档异常.type="+type+",projectName="+projectName,e);
            rtnMap.put("code","1");
            rtnMap.put("desc","获取工程相关文档异常.e:"+e.getMessage());
        }

        return this.getRtnMap(rtnMap,userInfo,object);
    }

    /**
     * 上传工程相关的文档
     * @param request
     * @return
     * @throws IOException
     */
    @RequestMapping("/uploadFile")
    @ResponseBody
    public Map<String,Object> uploadFile(HttpServletRequest request) throws IOException {
        Map<String,Object> rtnMap = new HashMap<>();
        logger.info("上传文件开始");
        LoginUser userInfo = UserInfoUtil.getUserInfo(request);
        if (userInfo == null){
            logger.info("上传文件,获取用户信息为空");
            return this.noUserRtn();
        }

        String projectName = request.getParameter("projectName");
        String type = request.getParameter("type");

        Assert.hasText(projectName,"上传文件,工程名为空");
        Assert.hasText(type,"上传文件,文件类型为空");

        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request;
        MultipartFile source = multipartRequest.getFile("file");
        if(source == null){
            logger.error("上传文件,文件错误.type="+type+",projectName="+projectName);
            rtnMap.put("code","1");
            rtnMap.put("desc","上传文件,文件错误.type="+type+",projectName="+projectName);
            return this.getRtnMap(rtnMap,userInfo,new JSONObject());
        }
        String fileName = source.getOriginalFilename();
        fileName = new String(fileName.getBytes("iso-8859-1"),"utf-8");
        String[] s = fileName.split("\\.");
        String suffix = s[s.length-1];
        if("sql".equals(type)){
            if(!"sql".equals(suffix)){
                logger.error("上传文件,文件类型错误.type="+type+",projectName="+projectName+",fileName="+fileName);
                rtnMap.put("code","1");
                rtnMap.put("desc","上传文件,文件类型错误.type="+type+",projectName="+projectName+",fileName="+fileName);
                return this.getRtnMap(rtnMap,userInfo,new JSONObject());
            }
        }else if("excel".equals(type)){
            if(!"xls".equals(suffix) && !"xlsx".equals(suffix)){
                logger.error("上传文件,文件类型错误.type="+type+",projectName="+projectName+",fileName="+fileName);
                rtnMap.put("code","1");
                rtnMap.put("desc","上传文件,文件类型错误.type="+type+",projectName="+projectName+",fileName="+fileName);
                return this.getRtnMap(rtnMap,userInfo,new JSONObject());
            }
        }else {
            logger.error("上传文件,参数错误.type="+type+",projectName="+projectName);
            rtnMap.put("code","1");
            rtnMap.put("desc","上传文件,参数错误.type="+type+",projectName="+projectName);
            return this.getRtnMap(rtnMap,userInfo,new JSONObject());
        }

        try {
            projectManager.uploadProjectFile(projectName,type,source,userInfo);
            rtnMap.put("code","0");
        } catch (Exception e) {
            logger.error("上传文件,保存文件异常.type="+type+",projectName="+projectName+",fileName="+fileName,e);
            rtnMap.put("code","1");
            rtnMap.put("desc","上传文件,保存文件异常.e:"+e.getMessage());
        }
        return this.getRtnMap(rtnMap,userInfo,new JSONObject());
    }

    /**
     * 编辑工程相关文档备注
     * @param request
     * @return
     * @throws IOException
     */
    @RequestMapping("/editProjectFileDesc")
    @ResponseBody
    public Map<String,Object> editProjectFileDesc(HttpServletRequest request) throws IOException {
        Map<String, Object> rtnMap = new HashMap<>();
        logger.info("编辑工程相关文档备注开始");
        LoginUser userInfo = UserInfoUtil.getUserInfo(request);
        if (userInfo == null) {
            logger.info("编辑工程相关文档备注,获取用户信息为空");
            return this.noUserRtn();
        }

        String projectName = request.getParameter("projectName");
        String type = request.getParameter("type");
        String fileName = request.getParameter("fileName");
        String desc = request.getParameter("desc");
        Assert.hasText(projectName, "编辑工程相关文档备注,工程名为空");
        Assert.hasText(type, "编辑工程相关文档备注,文件类型为空");
        Assert.hasText(fileName, "编辑工程相关文档备注,文件名为空");

        try {
            String path = ProjectUtil.getProjectFileDir(projectName,type)+"/"+fileName+".desc";
            File file = new File(path);
            if(!file.exists()){
                logger.error("编辑工程相关文档备注,文件不存在.path="+path);
                rtnMap.put("code","1");
                rtnMap.put("desc","编辑工程相关文档备注,文件不存在");
                return this.getRtnMap(rtnMap,userInfo,new JSONObject());
            }
            FileBaseInfo info = JSONFileUtil.getFileJsonForBean(path,FileBaseInfo.class);
            info.setDesc(desc);
            boolean flag = JSONFileUtil.saveFileJson(path,info);
            if(flag){
                rtnMap.put("code","0");
            }else {
                rtnMap.put("code","1");
                rtnMap.put("desc","编辑工程相关文档备注失败");
            }
        } catch (Exception e) {
            logger.error("编辑工程相关文档备注异常.type="+type+",projectName="+projectName+",fileName="+fileName,e);
            rtnMap.put("code","1");
            rtnMap.put("desc","编辑工程相关文档备注异常.e:"+e.getMessage());
        }
        return this.getRtnMap(rtnMap,userInfo,new JSONObject());
    }

    /**
     * 删除工程相关文档
     * @param request
     * @return
     * @throws IOException
     */
    @RequestMapping("/delProjectFile")
    @ResponseBody
    public Map<String,Object> delProjectFile(HttpServletRequest request) throws IOException {
        Map<String, Object> rtnMap = new HashMap<>();
        logger.info("删除工程相关文档开始");
        LoginUser userInfo = UserInfoUtil.getUserInfo(request);
        if (userInfo == null) {
            logger.info("删除工程相关文档,获取用户信息为空");
            return this.noUserRtn();
        }

        String projectName = request.getParameter("projectName");
        String type = request.getParameter("type");
        String fileName = request.getParameter("fileName");
        Assert.hasText(projectName, "您要删除的工程没有找到, 是否还没有指定工程?");
        Assert.hasText(type, "您要删除的工程类型没有扎到, 推测是代码bug, 请联络Beetle的开发人员");
        Assert.hasText(fileName, "待删除的文件名没有找到, 该文件可能已经删除.");

        try {
            String path = ProjectUtil.getProjectFileDir(projectName,type);
            File file = new File(path+"/"+fileName);
            if(file.exists()){
                file.delete();
            }
            File f = new File(path+"/"+fileName+".desc");
            if(f.exists()){
                f.delete();
            }
            rtnMap.put("code","0");
        } catch (Exception e) {
            logger.error("删除工程相关文档异常.type="+type+",projectName="+projectName+",fileName="+fileName,e);
            rtnMap.put("code","1");
            rtnMap.put("desc","删除工程相关文档异常.e:"+e.getMessage());
        }
        return this.getRtnMap(rtnMap,userInfo,new JSONObject());
    }

    /**
     * 下载工程相关文档
     * @param request
     * @param response
     */
    @RequestMapping("/downloadProjectFile")
    @ResponseBody
    public void downloadProjectFile(HttpServletRequest request, HttpServletResponse response) throws Exception{
        logger.info("下载工程相关文档开始");

        LoginUser userInfo = UserInfoUtil.getUserInfo(request);
        if (userInfo == null) {
            logger.info("下载工程相关文档时发生权限校验问题 原因:后台尝试获取用户信息对象,但得到的是空对象");
            return;
        }

        String projectName = request.getParameter("projectName");
        String type = request.getParameter("type");//sql excel

        String fileName = request.getParameter("fileName");
        boolean downloadAll = Boolean.parseBoolean(request.getParameter("downloadAll"));

        Assert.hasText(projectName, "由于没有指定工程, 无法下载对应的文件");
        Assert.hasText(type, "目标工程的类型未指定, 可能工程配置有误, 请联系 '"+projectName+"' 的开发人员重新维护工程配置.");
        String filePath = null;
        String path = ProjectUtil.getProjectFileDir(projectName,type);
        //fileName不为空  下载单个文件  fileName为空 且 downloadAll 为true 下载压缩包
        if(StringUtils.isEmpty(fileName) && !downloadAll){
            logger.error("尝试下载文档时发生了错误,文件名为空且没有选择'下载所有', 参数列表:->projectName="+projectName+",type="+type+",fileName="
                    +fileName+",downloadAll="+downloadAll);
            return;
        }

        if(StringUtils.isEmpty(fileName) && downloadAll){
            fileName = type + ".zip";
            filePath = path+".zip";
            ZipUtil.zip(filePath,path);
        }else {
            fileName = new String(fileName.getBytes("iso-8859-1"),"utf-8");
            filePath = path + File.separator + fileName;
        }

        if(StringUtils.isEmpty(filePath)){
            logger.error("尝试下载是发生异常,原因: filePath为空. 参数列表:projectName="+projectName+",type="+type+",fileName="
                    +fileName+",downloadAll="+downloadAll+",filePath="+filePath);
            return;
        }

        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition", "attachment;fileName="+new String(fileName.getBytes("utf-8"),"iso-8859-1"));

        InputStream inputStream = null;
        OutputStream os = null;
        try {
            inputStream = new FileInputStream(new File(filePath));
            os = response.getOutputStream();
            byte[] b = new byte[2048];
            int length;
            while ((length = inputStream.read(b)) > 0) {
                os.write(b, 0, length);
            }
        } catch (FileNotFoundException e) {

            logger.error("下载目标文件找不到. 参数列表:projectName="+projectName+",type="+type+",fileName="
                    +fileName+",downloadAll="+downloadAll+",filePath="+filePath, e);

        } catch (IOException e) {
            logger.error("IOException. 参数列表:projectName="+projectName+",type="+type+",fileName="
                    +fileName+",downloadAll="+downloadAll+",filePath="+filePath, e);

        }finally {
            try {
                os.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(fileName.endsWith(".zip") && downloadAll){
                File file = new File(filePath);
                if(file.exists()){
                    file.delete();
                }
            }
        }
    }
}
